using System;
using NUnit.Framework;

namespace NUnit.Behave.Specs.Scenario_Specs
{
    [TestFixture]
    [Category("Scenario_Specs")]
    public class When_creating_a_scenario
    {
        [Test]
        public void Should_accept_a_title_for_the_scenario()
        {
            string expectedTitle = "This is the scenario";
            Scenario scenario = new Scenario(expectedTitle);
            Assert.AreEqual(expectedTitle, scenario.Message);
        }
    }


    [TestFixture]
    [Category("Apple_Specs")]
    public class When_looking
    {
        [Test]
        public void Should_allow_multiple_givens_to_be_concatenated()
        {
            Scenario Apples_are_Washington_apples =
                new Scenario("Apples are Washington apples");

            Apples_are_Washington_apples
                .Given("The apple is", "Red")
                .And("The diameter of the apple is", 10)
                .When("I bite the apple", 2)
                .Then("the apples wieght should be", 25)
                .And("the apples internal color should start to", "brown");
        }
    }

    [TestFixture]
    [Category("Apple_Specs")]
    public class Apple_Specs
    {
        private Apple apple = null;

        [Test]
        public void Eating_an_apple()
        {
            Scenario Apples_are_Washington_apples =
                new Scenario("Apples are Washington apples");

            Apples_are_Washington_apples
                .Given("The apple is", "Red",
                       GivenTheAppleIs_Action())
                .And("The diameter of the apple is", 10,
                     GivenTheDiameterIs_Action())
                .When("I bite the apple", 2,
                      WhenIBiteTheApple_Action())
                .Then("the apples weight should be", 24,
                      ThenTheApplesWeight_Action())
                .And("the apples internal color should start to", "brown",
                     ThenTheApplesInternalColor_Action());

            Apples_are_Washington_apples
                .Given("The apple is", "Green")
                .And("The diameter of the apple is", 20)
                .When("I bite the apple", 10)
                .Then("the apples weight should be", 30)
                .And("the apples internal color should start to", "white");
        }

        private Action<int> ThenTheApplesWeight_Action()
        {
            return delegate(int weight)
                       {
                           Assert.AreEqual(weight, apple.Weight);
                       };
        }

        private Action<int> WhenIBiteTheApple_Action()
        {
            return delegate(int numberOfBites)
                       {
                           apple.Bite(numberOfBites);
                       };
        }

        private Action<string> GivenTheAppleIs_Action()
        {
            return delegate(string colorOfApple)
                       {
                           apple = new Apple(colorOfApple);
                       };
        }

        private Action<int> GivenTheDiameterIs_Action()
        {
            return delegate(int diameterOfApple)
                       {
                           apple.Diameter = diameterOfApple;
                       };
        }

        private Action<string> ThenTheApplesInternalColor_Action()
        {
            return delegate(string internalColor)
                       {
                           Assert.AreEqual(internalColor, apple.InternalColor);
                       };
        }
    }

    internal class Apple
    {
        private readonly string colorOfApple;
        private int diameter;
        private int weight;
        private string internalColor = "brown";
        private bool biteHasOccured;

        public Apple(string colorOfApple)
        {
            this.colorOfApple = colorOfApple;
        }

        public int Diameter
        {
            get { return diameter; }
            set { SetDiameterAndFigureWeight(value); }
        }

        private int SetDiameterAndFigureWeight(int value)
        {
            weight = value*3;

            return diameter = value;
        }

        public int Weight
        {
            get { return weight; }
        }

        public string InternalColor
        {
            get { return DetermineInternalColor(); }
        }

        private string DetermineInternalColor()
        {
            if (colorOfApple == "Red" && biteHasOccured)
                return "brown";

            return "white";
        }

        public void Bite(int bites)
        {
            biteHasOccured = true;
            int biteSize = bites*3;

            weight -= biteSize;
        }
    }
}